home *** CD-ROM | disk | FTP | other *** search
/ Die Ultimative Software-P…i Collection 1996 & 1997 / Die Ultimative Software-Pakete CD-ROM fur Atari Collection 1996 & 1997.iso / i / internet / software / tuwtcpsr / arp.c next >
Encoding:
C/C++ Source or Header  |  1993-02-25  |  6.4 KB  |  277 lines

  1. /* 
  2.  * ARP: Address Resolution Protocol Implementation
  3.  * 
  4.  * adapted for ATARI + RIEBL Card plus
  5.  * 
  6.  * FoRTec/hw/pm
  7.  *
  8.  * This package implements a very simple version of the Plummer Address
  9.  * Resolution Protocol (RFC 826).  It allows clients to resolve Internet
  10.  * addresses into Ethernet addresses, and knows how to respond to an
  11.  * address resolution request (when the transmit buffer is free).
  12.  * 
  13.  * Routines:
  14.  * 
  15.  *  arp_handler( pkt )             =>     1, if ARP packet and processed, 
  16.  *                                    0, if no packet there otherwise
  17.  *                                  < 0, if network error
  18.  *  arp_in2haddr(inaddr,haddr)    =>    1 if did it, 
  19.  *                                    0 if couldn't.
  20.  *
  21.  *    arp_init()                    => < 0, if network error
  22.  *                                   >=0, if ok
  23.  *    arp_exit()                    => < 0, if network error
  24.  *                                   >=0, if ok
  25.  */
  26.  
  27. #include <stdio.h>
  28. #include <stdlib.h>
  29. #include <string.h>
  30. #include <time.h>
  31. #include "pktdrv.h"
  32. #include "ip.h"
  33. #include "arp.h"
  34.  
  35. #include "nettrace.h"
  36.  
  37. #define noDEBUG
  38.  
  39. static INADDR arp_reply;    /* replied internet address */
  40. static arp_cache arp_tab[ARPCACHESIZE] = {0};    /* init to zero */
  41. #define ARP_ADDIDX    0    /* use last entry for immediate replies */
  42. #define ARP_GATEWAY 1    /* gateway entry */
  43. #define ARP_BASE     2
  44.  
  45. int    arp_rcv(int,char *);
  46. static int arp_idx = ARP_ADDIDX+ARP_BASE;
  47. static int arp_handle = ENOTINST;
  48. static volatile ARP_PACKET *arp_pkt = NULL;
  49. long arp_counts[2] = {0L,0L};
  50.  
  51. int arp_init()
  52. {
  53. int i;
  54.     
  55.     for(i=0; i< ARPCACHESIZE; i++)
  56.         arp_tab[i].inaddr = 0L;
  57.     arp_handle = net_open(ET_ARP,arp_rcv);
  58. #ifdef DEBUG
  59.     printf("arp_init\n");
  60. #endif
  61.     
  62.     if(arp_handle < 0) return(arp_handle);
  63.     
  64.     if(!net_demux(TRUE,arp_handler))
  65.     {
  66.         net_release(arp_handle);
  67.         arp_pkt = NULL;
  68.         return(ENOTINST);
  69.     }
  70.     return(arp_handle);
  71. }
  72.  
  73. int arp_exit()
  74. {
  75. int i;
  76. #ifdef DEBUG
  77.     printf("arp_exit\n");
  78. #endif
  79.   if(arp_handle < 0) return(FALSE);
  80.   i = net_release(ET_ARP);
  81. #ifdef DEBUG
  82.   printf("net_release = %d\n",i);
  83. #endif
  84.   net_demux(FALSE,arp_handler);            /* remove from demux tab */
  85. #ifdef DEBUG
  86.   printf("arp_exit\n");
  87. #endif
  88.   return(i>=0);
  89. }
  90.  
  91.  
  92. int arp_rcv(int length, char *pkt)
  93. {
  94.     if(arp_pkt) return(FALSE);        /* already processing a arp packet */
  95.     arp_pkt = (ARP_PACKET *)pkt;
  96.     return(TRUE);
  97. }    
  98.  
  99. int    arp_add2tab(INADDR inaddr,HADDR haddr)
  100. {
  101. register int i;
  102.     for(i=0; i<ARPCACHESIZE; i++)
  103.         if(arp_tab[i].inaddr == inaddr) return (TRUE);
  104.         
  105.     /* add entry only if it's not already there */    
  106.     memcpy(arp_tab[ARP_ADDIDX].haddr,haddr,sizeof(HADDR));
  107.     arp_tab[ARP_ADDIDX].inaddr = inaddr;
  108.     return(TRUE);    
  109. }
  110.  
  111. int    arp_addgw(INADDR inaddr,HADDR haddr)
  112. {
  113.     memcpy(arp_tab[ARP_GATEWAY].haddr,haddr,sizeof(HADDR));
  114.     arp_tab[ARP_GATEWAY].inaddr = inaddr;
  115.     return(TRUE);    
  116. }
  117.  
  118.  
  119.  
  120. int arp_handler(void)
  121. {
  122. register ARP     *ap;
  123. register int    i;
  124. extern INADDR    lcl_inaddr;
  125.  
  126.     if(!arp_pkt) return(FALSE);        /* no packet received */
  127.  
  128.     ap = arp_head(arp_pkt);
  129. #ifdef DEBUG
  130.     printf("arp got from %8lx for %8lx\n",ap->src_inaddr,ap->dst_inaddr);
  131. #endif
  132.     i=0;
  133.     if (ap->hw_type == ARP_ET &&         /* have ethernet hardware, */
  134.         ap->protocol == ET_IP &&         /* and internet software, */
  135.           ap->dst_inaddr == lcl_inaddr)      /* for my addr. */
  136.     {
  137.     arp_counts[0]++;
  138.     switch(ap->opcode)
  139.     {
  140.         case ARP_REQUEST:  /* be a resolution req. */
  141. #ifdef DEBUG
  142. printf("arp REQUEST\n");
  143. #endif
  144.             /* format response. */
  145.             
  146.             ap->hw_len = (u_char)sizeof(HADDR);
  147.             ap->pr_len = (u_char)sizeof(INADDR);
  148.             
  149.             ap->opcode = ARP_REPLY;
  150.             ap->dst_inaddr = ap->src_inaddr;
  151.             ap->src_inaddr = lcl_inaddr;
  152.             
  153.             memcpy(ap->dst_haddr, ap->src_haddr, sizeof(HADDR));
  154.                         /* fill ethernet header */
  155.             memcpy(arp_pkt->et.et_dest, ap->src_haddr, sizeof(HADDR));
  156.             arp_pkt->et.et_type = ET_ARP;
  157.             net_getadr((int)sizeof(HADDR),ap->src_haddr);
  158.             memcpy(arp_pkt->et.et_src, ap->src_haddr, sizeof(HADDR));
  159.             arp_counts[1]++;
  160.             i = net_send(ARP_PKTSIZE,(char *)arp_pkt);
  161. #ifdef DEBUG
  162. printf("arp replied \n");
  163. #endif
  164.             break;
  165.         case ARP_REPLY:
  166. #ifdef DEBUG
  167. printf("arp got reply\n");
  168. #endif
  169.             for(i=0; i<ARPCACHESIZE; i++)
  170.             {
  171.                 if(arp_tab[i].inaddr == ap->src_inaddr)
  172.                     break;
  173.             }
  174.             if(i==ARPCACHESIZE) break;    /* I'm not waiting for a arp reply */
  175.  
  176.             memcpy(arp_tab[i].haddr,ap->src_haddr,sizeof(HADDR));
  177.             arp_tab[i].timeout = 0L;
  178.             arp_tab[i].resend = 0;
  179.             arp_reply = 0L;
  180.             i=0;
  181.             break;
  182.      }
  183.     }
  184.     if(!net_pktfree((char *)arp_pkt))
  185.     {
  186. #ifdef DEBUG
  187.         printf("couldn't free arp packet\n");
  188. #endif
  189.     }
  190.     arp_pkt = NULL;            /* drop packet */
  191.     return (i);
  192. }
  193.  
  194. /* 
  195.  * Do an address resolution bit.
  196.  */
  197. int arp_in2haddr(INADDR inaddr,HADDR haddr)
  198. {
  199. ARP               *ap;
  200. int             i;
  201. extern INADDR     lcl_inaddr;
  202. extern HADDR    bcst_haddr;
  203. ARP_PACKET         *arp_send;
  204.  
  205.  
  206.     if(inaddr == lcl_inaddr)
  207.     {            /* asked for own haddr */
  208.         net_getadr((int)sizeof(HADDR),haddr);
  209.         return(ARP_OK);
  210.     }
  211.           /* do a cachelookup */
  212.     for(i=0; i<ARPCACHESIZE; i++)
  213.         if(arp_tab[i].inaddr == inaddr)
  214.         {                /* found in cache */
  215.             if(arp_tab[i].timeout)
  216.             {
  217.                 if(arp_tab[i].timeout <= clock()) break;
  218.                 return(ARP_WAIT);
  219.             }
  220.             memcpy(haddr, (char *)arp_tab[i].haddr, sizeof(HADDR));
  221.             return (ARP_OK);
  222.         }
  223.     if(i==ARPCACHESIZE)
  224.     {
  225.         arp_tab[arp_idx].inaddr = inaddr;
  226.         arp_tab[arp_idx].timeout = clock()+ARP_TIMEOUT;
  227.         arp_tab[arp_idx].resend = 0;
  228.         if(++arp_idx >= ARPCACHESIZE)
  229.             arp_idx = ARP_ADDIDX+ARP_BASE;        /* wrap around */
  230.  
  231.     }
  232.     else
  233.     {
  234.         if(arp_tab[i].resend >= ARP_RETRIES)
  235.         {
  236.             arp_tab[i].inaddr = 0L;
  237.             return(ARP_FAIL);
  238.         }
  239.         arp_tab[i].timeout = clock()+ARP_TIMEOUT;
  240.         arp_tab[i].resend++;
  241.     }
  242.     arp_send = (ARP_PACKET *)net_pktalloc(ET_ARP);
  243.     if(!arp_send)
  244.     {
  245. #ifdef DEBUG
  246.         printf("arp: no packet\n");
  247. #endif
  248.         arp_tab[i].inaddr = 0L;
  249.         return(ARP_FAIL);
  250.     }
  251.     arp_send->et.et_type = ET_ARP;
  252.        memset(arp_send->et.et_dest,0xff,sizeof(HADDR));
  253.     net_getadr((int)sizeof(HADDR),arp_send->et.et_src);
  254.        ap = &arp_send->arp;
  255.     ap->hw_type = ARP_ET;
  256.     ap->protocol = ET_IP;
  257.     ap->hw_len = (u_char)sizeof(HADDR);
  258.     ap->pr_len = (u_char)sizeof(INADDR);
  259.     ap->opcode = ARP_REQUEST;
  260.     ap->src_inaddr = lcl_inaddr;
  261.     net_getadr((int)sizeof(HADDR),ap->src_haddr);
  262.     ap->dst_inaddr = inaddr;
  263.                 /* ...and send the packet */
  264.     arp_counts[1]++;
  265.     i = net_send(ARP_PKTSIZE,(char *)arp_send );
  266. #ifdef DEBUG
  267.         printf("arp sent req for %lx\n",inaddr);
  268. #endif
  269.     net_pktfree((char *)arp_send);
  270.     if(i<0)
  271.     {
  272.         arp_tab[i].inaddr = 0L;
  273.         return(i);
  274.     }
  275.     return(ARP_WAIT);
  276. }
  277.